package com.leetcode.problems;

import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * -@Version 1.0
 * -@Author:Vpen
 * -@Date:2021/1/28 10:18
 * -@Content:
 * 给定一个整数数组 nums和一个整数目标值 target，请你在该数组中找出 和为目标值 的那两个整数，并返回它们的数组下标。
 * 你可以假设每种输入只会对应一个答案。但是，数组中同一个元素不能使用两遍。
 * 你可以按任意顺序返回答案。
 * 示例 1：
 * 输入：nums = [2,7,11,15], target = 9
 * 输出：[0,1]
 * 解释：因为 nums[0] + nums[1] == 9 ，返回 [0, 1] 。
 *
 * 示例 2：
 * 输入：nums = [3,2,4], target = 6
 * 输出：[1,2]
 *
 * 示例 3：
 * 输入：nums = [3,3], target = 6
 * 输出：[0,1]
 *
 */

class TwoNumSum {
    public static void main(String[] args) {
       TwoNumSum t1=  new TwoNumSum();
        int[] sum=t1.twoSum(new int[]{1,2,3},5);
        t1.show(sum);
    }

    public int[] twoSum(int[] nums, int target) {
        // k是唯一 值不唯一，所以把nums作为k 下标作为值
        Map<Integer, Integer> map = new HashMap<>();

        for (int i = 0; i < nums.length; i++) {
            // 5-1=4
            // 5-2=3
            // 5-3=2
            int sub = target-nums[i];

            if (map.containsKey(sub)) {
                // 2,map.get(2)
                return new int[]{i,map.get(sub)};
            }
            // 1,0
            // 2,1
            //
            map.put(nums[i],i);
        }
        throw new IllegalArgumentException("No two Num");
    }

    public void show(int[] arr){
        for (int x : arr) {
            System.out.print(x+" ");
        }
    }
}


/**
 * 作者:Vpen
 * 描述:
 * 给定一个整数类型的数组nums，请编写一个能够返回数组 “中心索引” 的方法。
 * 我们是这样定义数组 中心索引 的：数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
 * 如果数组不存在中心索引，那么我们应该返回 -1。如果数组有多个中心索引，那么我们应该返回最靠近左边的那一个。
 * nums = [1, 7, 3, 6, 5, 6]
 * 输出：3
 * 解释：
 * 索引 3 (nums[3] = 6) 的左侧数之和 (1 + 7 + 3 = 11)，与右侧数之和 (5 + 6 = 11) 相等。
 * 同时, 3 也是第一个符合要求的中心索引。

 *
 * */

/**
 * 作者:Vpen
 * 描述:
 * 错误解法
 * */
class Solution {
    public int pivotIndex(int[] nums) {
        int n = nums.length;
        if (n==1||n==0) {
            return -1;
        }
        int j=0;
        int k=n-1;
        int L=nums[j];
        int R=nums[k];

        for (int i = 0; i < n; i++) {
            if (L==R && j<k && (k-j)!=1){
                return j+1;
            }
            if (L<R){
                L+=nums[j+1];
                j++;
            }else {
                R+=nums[k-1];
                k--;
            }
        }
        return -1;
    }
}

public class TestSolution{
    @Test
    public void test1(){
        Solution solution = new Solution();
        int i = solution.pivotIndex(new int[]{-1,-1,-1,-1,-1,-1});
        System.out.println(i);
    }
}


/**
* -@author Vpen
* -@name
* -@date 2021/6/5 22:16
* -@param
* -@return
* -@作用:给定一个非空整数数组，除了某个元素只出现一次以外，其余每个元素均出现两次。找出那个只出现了一次的元素。
 * 示例 1:
 *
 * 输入: [2,2,1]
 * 输出: 1
 *
 * 示例 2:
 *
 * 输入: [4,1,2,1,2]
 * 输出: 4
*/
class Solution1 {
    public static void main(String[] args) {
        Solution1 solution1 = new Solution1();
        int i = solution1.singleNumber(new int[]{2, 2, 1,1,4});
        System.out.println(i);

        int i1 = solution1.singleNumber2(new int[]{1, 1, 2, 2, 3});
        System.out.println(i1);

        System.out.println(solution1.isUnique("leea"));

    }

    /**
     * 作者:Vpen
     * 描述:使用集合存储数字。
     * 遍历数组中的每个数字，
     * 如果集合中没有该数字，
     * 则将该数字加入集合，
     * 如果集合中已经有该数字，
     * 则将该数字从集合中删除，
     * 最后剩下的数字就是只出现一次的数字。
     *
     * */
    public int singleNumber(int[] nums) {

        HashSet set = new HashSet();
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            // 如果集合有这个数组就删除
            if (set.contains(nums[i])){
                set.remove(nums[i]);
            }else { // 没有就移除
                set.add(nums[i]);
            }
        }
        return (int) set.iterator().next();// 获取集合种的第一个元素
    }

    public int singleNumber2(int[] nums){
        /**
         * 作者:Vpen
         * 描述:答案是使用位运算。对于这道题，可使用异或运算 ⊕\oplus⊕。异或运算有以下三个性质。
         *     任何数和 000 做异或运算，结果仍然是原来的数，即 a⊕0=aa \oplus 0=aa⊕0=a。
         *     任何数和其自身做异或运算，结果是 000，即 a⊕a=0a \oplus a=0a⊕a=0。
         *     异或运算满足交换律和结合律，即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=ba \oplus b \oplus a=b \oplus a \oplus a=b \oplus (a \oplus a)=b \oplus0=ba⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b。
         * */
        int single = 0;
        for (int num : nums) {
            single= single^num;
        }
        return single;
    }
    /**
     * 作者:Vpen
     * 描述:实现一个算法，确定一个字符串 s 的所有字符是否全都不同。
     *
     * 示例 1：
     *
     * 输入: s = "leetcode"
     * 输出: false
     *
     * 示例 2：
     *
     * 输入: s = "abc"
     * 输出: true
     *
     * 来源：力扣（LeetCode）
     * 链接：https://leetcode-cn.com/problems/is-unique-lcci
     * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
     * */
    public boolean isUnique(String astr) {

        int length = astr.length();
        int i,j;
        boolean flag=true;
        for (i = 0; i < length; i++) {
            char t1 = astr.charAt(i);
            for (j = i+1; j < length; j++) {
                char t2 = astr.charAt(j);
                if (t1==t2){
                    flag=false;
                    break;
                }
            }
        }

        return flag;
    }


}